home *** CD-ROM | disk | FTP | other *** search
Text File | 1989-08-27 | 31.1 KB | 1,272 lines |
- Newsgroups: comp.sources.misc
- subject: v08i021: Rpn v1.1
- From: allbery@uunet.UU.NET (Brandon S. Allbery - comp.sources.misc)
- Reply-To: egray@fthood.UUCP
-
- Posting-number: Volume 8, Issue 21
- Submitted-by: egray@fthood.UUCP
- Archive-name: rpn_eg
-
- [I see a few "questional" preprocessor constructs in this code. ++bsa]
-
- Rpn is a public domain "pop up" reverse polish notation calculator that
- is designed to have the same (dare I say?) "look and feel" of the
- Hewlett-Packard HP-16c. It can compile on virtually any flavor of Unix
- and MSDOS. The MSDOS version will require the public domain PC Curses
- package.
-
- I've included both the nroff version of the Unix manual page and the
- "ASCII'ized" version for folks (like MSDOS) without the Document Writers
- Workbench. A makefile isn't required... it's only one file.
-
- Have fun...
-
- Emmet P. Gray US Army, HQ III Corps & Fort Hood
- ...!uunet!uiucuxc!fthood!egray Attn: AFZF-DE-ENV
- fthood!egray@uxc.cso.uiuc.edu Directorate of Engineering & Housing
- Environmental Management Office
- Fort Hood, TX 76544-5057
-
- ------------------------------------------------------------------------------
- #! /bin/sh
- # This is a shell archive, meaning:
- # 1. Remove everything above the #! /bin/sh line.
- # 2. Save the resulting text in a file.
- # 3. Execute the file with /bin/sh (not csh) to create:
- # rpn.c
- # rpn.1
- # rpn.man
- # This archive created: Fri Aug 25 14:51:23 1989
- export PATH; PATH=/bin:/usr/bin:$PATH
- echo shar: "extracting 'rpn.c'" '(19008 characters)'
- if test -f 'rpn.c'
- then
- echo shar: "will not over-write existing file 'rpn.c'"
- else
- sed 's/^X//' << \SHAR_EOF > 'rpn.c'
- X/*
- X * Simple RPN (Reverse Polish Notation) calculator. Layout and functions
- X * loosely modeled after the HP-16c. MSDOS versions will require the
- X * PC Curses package.
- X *
- X * on Unix compile with:
- X * cc -O [-f] -s rpn.c -o rpn -lm -lcurses [-ltermcap] [-lc_s]
- X *
- X * Emmet P. Gray US Army, HQ III Corps & Fort Hood
- X * ...!uunet!uiucuxc!fthood!egray Attn: AFZF-DE-ENV
- X * fthood!egray@uxc.cso.uiuc.edu Directorate of Engineering & Housing
- X * Environmental Management Office
- X * Fort Hood, TX 76544-5057
- X */
- X
- X#undef OLD_CURSES /* for old Xenix and Berkeley */
- X#undef MSDOS /* for MSDOS (requires PC Curses) */
- X#undef XENIX_3 /* for old Xenix 3.0/3.5 */
- X#undef BIG_END_FIRST /* for Intel style CPU's */
- X#undef ANSI_C /* for ANSI C */
- X
- X#include <stdio.h>
- X#include <math.h>
- X#include <curses.h>
- X
- X#ifdef ANSI_C
- X#include <limits.h>
- X#include <float.h>
- X#else /* ANSI_C */
- X#define LONG_MAX 0x7fffffff
- X#define ULONG_MAX 0xffffffff
- X#define DBL_DIG 15
- X#define DBL_MAX 1.7976931348623167e+308
- X#endif /* ANSI_C */
- X
- X#define DBL_ULONG_MAX 4294967295.0 /* ULONG_MAX as a double */
- X
- X#ifdef OLD_CURSES
- X#define wattron(win,A_REVERSE) wstandout(win)
- X#define wattroff(win,A_REVERSE) wstandend(win)
- X#define wattrset(win,A_NORMAL) wstandend(win)
- X#define cbreak crmode
- Xchar tb[1024];
- X#endif /* OLD_CURSES */
- X
- X#ifdef MSDOS
- X#define what_is_at(w,a,b) (w->_line[a][b])
- X#define getenv strdup
- X#else /* MSDOS */
- X#define what_is_at(w,a,b) (w->_y[a][b])
- X#endif /* MSDOS */
- X /* some fundamental contstants */
- X#define MAX_LOGICAL 0xffffffff
- X#define SCREEN_SIZE 36
- X#define STACK_SIZE 5
- X#define MAX_FLOAT_DIGITS SCREEN_SIZE-1
- X#define MAX_HEX_DIGITS 8
- X#define MAX_OCTAL_DIGITS 11
- X#define MAX_DECIMAL_DIGITS 10
- X#define MAX_BINARY_DIGITS 32
- X#define DECIMAL_PLACES 8
- X /* operating modes */
- X#define FLOAT 0
- X#define HEX 1
- X#define DECIMAL 2
- X#define OCTAL 3
- X#define BINARY 4
- X /* location of calculator on screen */
- X#define BASE_Y 5
- X#define BASE_X 0
- X
- Xstruct layout {
- X char key;
- X int y;
- X int x;
- X};
- X
- Xdouble stack[STACK_SIZE] = {0.0};
- Xdouble sto[10] = {0.0};
- Xchar blank[SCREEN_SIZE + 1];
- X
- Xmain(argc, argv)
- Xint argc;
- Xchar *argv[];
- X{
- X int i, mode, store_it, position, over_flow, x, y, help_is_showing;
- X int got_decimal, got_exponent, want_out, decimal_places;
- X unsigned long int_part, dtoul();
- X double op2, current, pop(), convert();
- X char c, c1, input[SCREEN_SIZE], *strchr(), *memset(), *term, *getenv();
- X char output[SCREEN_SIZE + 1], *bitpattern(), last_operator, *strcpy();
- X void push(), exit(), paint_calc(), flash_key(), clear_display();
- X WINDOW *win, *hwin, *help(), *newwin();
- X
- X /* initialize the terminal */
- X term = getenv("TERM");
- X if (term == NULL || *term == '\0') {
- X printf("%s: TERM not defined...\n", argv[0]);
- X exit(1);
- X }
- X /* i=1 required for PC curses */
- X i = 1;
- X#ifdef OLD_CURSES
- X i = tgetent(tb, term);
- X#else /* OLD_CURSES */
- X setupterm(term, 1, &i);
- X#endif /* OLD_CURSES */
- X if (i != 1) {
- X printf("%s: No terminfo data for '%s'...\n", argv[0], term);
- X exit(1);
- X }
- X initscr();
- X cbreak();
- X noecho();
- X#ifdef XENIX_3
- X raw();
- X#endif /* XENIX_3 */
- X /* percision in the display */
- X if (argc > 1 && *argv[1] == '-') {
- X decimal_places = atoi(&argv[1][1]);
- X if (decimal_places < 0)
- X decimal_places = 0;
- X if (decimal_places > DBL_DIG)
- X decimal_places = DBL_DIG;
- X }
- X else
- X decimal_places = DECIMAL_PLACES;
- X
- X win = newwin(15, 47, BASE_Y, BASE_X);
- X paint_calc(win);
- X
- X memset(blank, ' ', SCREEN_SIZE);
- X blank[SCREEN_SIZE] = '\0';
- X current = 0.0;
- X position = 0;
- X mode = FLOAT;
- X help_is_showing = 0;
- X last_operator = 0;
- X got_decimal = 0;
- X got_exponent = 0;
- X want_out = 0;
- X
- X while (1) {
- X c = wgetch(win);
- X /* erase the help window */
- X if (help_is_showing) {
- X help_is_showing = 0;
- X werase(hwin);
- X wrefresh(hwin);
- X delwin(hwin);
- X
- X touchwin(win);
- X wrefresh(win);
- X }
- X
- X store_it = 0;
- X over_flow = 0;
- X /* get incoming digits */
- X switch (mode) {
- X case FLOAT:
- X if (strchr("0123456789.eE+-", c) != NULL)
- X store_it++;
- X switch (c) {
- X case '.':
- X if (got_decimal || got_exponent)
- X store_it = 0;
- X got_decimal++;
- X break;
- X case 'e':
- X case 'E':
- X if (!position || got_exponent)
- X store_it = 0;
- X got_exponent++;
- X break;
- X
- X /*
- X * Is it an operator or is it
- X * the sign of the exponent?
- X */
- X case '+':
- X case '-':
- X if (!position || (input[position - 1] != 'e' && input[position - 1] != 'E'))
- X store_it = 0;
- X break;
- X }
- X if (position >= MAX_FLOAT_DIGITS)
- X over_flow++;
- X break;
- X case HEX:
- X if (strchr("0123456789abcdef", c) != NULL)
- X store_it++;
- X if (position >= MAX_HEX_DIGITS)
- X over_flow++;
- X break;
- X case OCTAL:
- X if (strchr("01234567", c) != NULL)
- X store_it++;
- X if (position >= MAX_OCTAL_DIGITS)
- X over_flow++;
- X break;
- X case DECIMAL:
- X if (strchr("0123456789", c) != NULL)
- X store_it++;
- X if (position >= MAX_DECIMAL_DIGITS)
- X over_flow++;
- X break;
- X case BINARY:
- X if (strchr("01", c) != NULL)
- X store_it++;
- X if (position >= MAX_BINARY_DIGITS)
- X over_flow++;
- X break;
- X }
- X /* store digits */
- X if (store_it) {
- X if (over_flow) {
- X fputc(7, stderr);
- X continue;
- X }
- X flash_key(win, c);
- X if (!position)
- X clear_display(win);
- X waddch(win, c);
- X wrefresh(win);
- X
- X input[position++] = c;
- X input[position] = '\0';
- X continue;
- X }
- X /* process pseudo operators */
- X switch (c) {
- X case 'q': /* time to quit? */
- X case 'Q':
- X want_out++;
- X break;
- X case '\b': /* do a backspace */
- X if (position) {
- X input[--position] = '\0';
- X flash_key(win, c);
- X getyx(win, y, x);
- X x--;
- X wmove(win, y, x);
- X waddch(win, ' ');
- X wmove(win, y, x);
- X wrefresh(win);
- X }
- X else
- X fputc(7, stderr);
- X continue;
- X case '?': /* help! */
- X flash_key(win, c);
- X hwin = help();
- X help_is_showing = 1;
- X continue;
- X default:
- X break;
- X }
- X if (want_out)
- X break;
- X /* test for valid operator */
- X if (strchr("/FhHDoOB*&|lLxX\r\n-^~sSrRC+", c) == NULL) {
- X fputc(7, stderr);
- X continue;
- X }
- X /* if you've got input, convert it */
- X if (position) {
- X current = convert(input, mode);
- X
- X /*
- X * This is a little weird... if the last operator was
- X * the <enter>, then replace (rather than push) the
- X * value on stack.
- X */
- X if (last_operator == '\r' || last_operator == '\n')
- X stack[0] = current;
- X else
- X push(current);
- X
- X position = 0;
- X input[0] = '\0';
- X got_decimal = 0;
- X got_exponent = 0;
- X }
- X /* process "real" operators */
- X switch (c) {
- X case '\r':
- X case '\n':
- X push(current);
- X break;
- X case '+':
- X current = pop() + pop();
- X push(current);
- X break;
- X case '-':
- X op2 = pop();
- X current = pop() - op2;
- X push(current);
- X break;
- X case '*':
- X current = pop() * pop();
- X push(current);
- X break;
- X case '/':
- X op2 = pop();
- X if (op2 == 0.0) {
- X clear_display(win);
- X mvwaddstr(win, 3, 5, "divide by zero");
- X wrefresh(win);
- X continue;
- X }
- X current = pop() / op2;
- X push(current);
- X break;
- X case 'C': /* change sign */
- X current = pop() * -1.0;
- X push(current);
- X break;
- X case 'F': /* float */
- X mode = FLOAT;
- X mvwaddch(win, 3, SCREEN_SIZE + 5, ' ');
- X wmove(win, 3, 5);
- X break;
- X case 'h':
- X case 'H': /* hex */
- X mode = HEX;
- X mvwaddch(win, 3, SCREEN_SIZE + 5, 'h');
- X wmove(win, 3, 5);
- X break;
- X case 'D': /* decimal */
- X mode = DECIMAL;
- X mvwaddch(win, 3, SCREEN_SIZE + 5, 'd');
- X wmove(win, 3, 5);
- X break;
- X case 'o':
- X case 'O': /* octal */
- X mode = OCTAL;
- X mvwaddch(win, 3, SCREEN_SIZE + 5, 'o');
- X wmove(win, 3, 5);
- X break;
- X case 'B': /* binary */
- X mode = BINARY;
- X mvwaddch(win, 3, SCREEN_SIZE + 5, 'b');
- X wmove(win, 3, 5);
- X break;
- X case '&': /* and */
- X int_part = dtoul(pop()) & dtoul(pop());
- X current = int_part;
- X push(current);
- X break;
- X case '|': /* or */
- X int_part = dtoul(pop()) | dtoul(pop());
- X current = int_part;
- X push(current);
- X break;
- X case '^': /* exclusive or */
- X int_part = dtoul(pop()) ^ dtoul(pop());
- X current = int_part;
- X push(current);
- X break;
- X case '~': /* 1's complement */
- X int_part = (~dtoul(pop()) & MAX_LOGICAL);
- X current = int_part;
- X push(current);
- X break;
- X case 'x':
- X case 'X': /* xchg x and y */
- X op2 = pop();
- X current = pop();
- X push(op2);
- X push(current);
- X break;
- X case 's':
- X case 'S': /* store */
- X flash_key(win, c);
- X c1 = wgetch(win);
- X if (strchr("0123456789", c1) == NULL) {
- X fputc(7, stderr);
- X continue;
- X }
- X /* doesn't disturb the stack */
- X sto[c1 - '0'] = current;
- X break;
- X case 'r':
- X case 'R': /* recall */
- X flash_key(win, c);
- X c1 = wgetch(win);
- X if (strchr("0123456789", c1) == NULL) {
- X fputc(7, stderr);
- X continue;
- X }
- X current = sto[c1 - '0'];
- X push(current);
- X break;
- X case 'l':
- X case 'L': /* roll the stack */
- X op2 = stack[0];
- X for (i = 0; i < STACK_SIZE - 1; i++)
- X stack[i] = stack[i + 1];
- X stack[STACK_SIZE - 1] = op2;
- X current = stack[0];
- X break;
- X default:
- X fputc(7, stderr);
- X continue;
- X }
- X last_operator = c;
- X /* display operator key */
- X flash_key(win, c);
- X /* convert double to unsigned long */
- X if (mode != FLOAT)
- X int_part = dtoul(current);
- X
- X /*
- X * Dectect overflows in float mode only. It's OK to overflow
- X * in the hex/dec/oct/bin modes.
- X */
- X if (mode == FLOAT && fabs(current) >= DBL_MAX) {
- X clear_display(win);
- X mvwaddstr(win, 3, 5, "overflow");
- X wrefresh(win);
- X continue;
- X }
- X /* print the answer */
- X switch (mode) {
- X case FLOAT:
- X sprintf(output, "%.*g", decimal_places, current);
- X break;
- X case HEX:
- X sprintf(output, "%lx", int_part);
- X break;
- X case OCTAL:
- X sprintf(output, "%lo", int_part);
- X break;
- X case DECIMAL:
- X sprintf(output, "%lu", int_part);
- X break;
- X case BINARY:
- X strcpy(output, bitpattern(int_part));
- X break;
- X }
- X clear_display(win);
- X waddstr(win, output);
- X wmove(win, 3, 5);
- X wrefresh(win);
- X }
- X
- X#ifdef OLD_CURSES
- X move(LINES - 1, 0);
- X refresh();
- X#endif /* OLD_CURSES */
- X endwin();
- X exit(0);
- X}
- X
- X/*
- X * Push a number on the stack. If the stack is full, the "top" value
- X * is lost.
- X */
- X
- Xvoid
- Xpush(f)
- Xdouble f;
- X{
- X int i;
- X
- X for (i = STACK_SIZE - 1; i > 0; i--)
- X stack[i] = stack[i - 1];
- X stack[0] = f;
- X return;
- X}
- X
- X/*
- X * Pop a value off the stack. The "top" value is always preserved.
- X */
- X
- Xdouble
- Xpop()
- X{
- X int i;
- X double f;
- X
- X f = stack[0];
- X for (i = 0; i < STACK_SIZE - 1; i++)
- X stack[i] = stack[i + 1];
- X return (f);
- X}
- X
- X/*
- X * Convert a double to an unsigned long. Some (most?) systems will generate
- X * a FPE (Floating Point Exception) if you attempt to assign a double that
- X * is greater than LONG_MAX.
- X */
- X
- Xunsigned long
- Xdtoul(d)
- Xdouble d;
- X{
- X double temp;
- X unsigned long ans;
- X /* is it too big for assignment? */
- X if (fabs(d) > LONG_MAX) {
- X /* chop it to a resonable size */
- X temp = fmod(d, DBL_ULONG_MAX);
- X /*
- X * if the fmod() returns a zero, then the number is just too
- X * big to fit any useful information in 32 bits.
- X */
- X if (temp == 0.0)
- X ans = ULONG_MAX;
- X else {
- X if (temp > LONG_MAX) {
- X ans = (temp - LONG_MAX);
- X ans += LONG_MAX;
- X }
- X else
- X ans = temp;
- X }
- X /* boundary condition at zero */
- X if (temp != 0.0 && d > DBL_ULONG_MAX)
- X ans -= 1L;
- X }
- X else /* gee, isn't this soooo much easier? */
- X ans = d;
- X
- X return (ans & MAX_LOGICAL);
- X}
- X
- X/*
- X * Convert an ascii "number" into a double. Handles hex/oct/bin digits.
- X */
- X
- Xdouble
- Xconvert(buf, mode)
- Xchar *buf;
- Xint mode;
- X{
- X double f, atof();
- X unsigned long strtoul();
- X
- X switch (mode) {
- X case DECIMAL:
- X case FLOAT:
- X f = atof(buf);
- X break;
- X case HEX:
- X f = (double) strtoul(buf, (char **) NULL, 16);
- X break;
- X case OCTAL:
- X f = (double) strtoul(buf, (char **) NULL, 8);
- X break;
- X case BINARY:
- X f = (double) strtoul(buf, (char **) NULL, 2);
- X break;
- X }
- X return (f);
- X}
- X
- X/*
- X * Convert a number into its binary bit pattern. Returns a pointer to
- X * a static buffer. The BIG_END_FIRST pre-processor macro determines if
- X * the number is stored "big end first" on your processor.
- X */
- X
- Xchar *
- Xbitpattern(val)
- Xunsigned long val;
- X{
- X unsigned char c, *p;
- X int i, j, size, printed, bp;
- X static char bitbuf[SCREEN_SIZE];
- X
- X /* max of 32 bits */
- X size = sizeof(val);
- X if (size > 4)
- X size = 4;
- X
- X p = (unsigned char *) &val;
- X#ifdef BIG_END_FIRST
- X p += size - 1;
- X#endif /* BIG_END_FIRST */
- X
- X bp = 0;
- X printed = 0;
- X for (i = 1; i <= size; i++) {
- X c = *p;
- X#ifdef BIG_END_FIRST
- X p--;
- X#else /* BIG_END_FIRST */
- X p++;
- X#endif /* BIG_END_FIRST */
- X if (c == 0 && !printed && i != size)
- X continue;
- X for (j = 7; j >= 0; j--)
- X bitbuf[bp++] = ((c >> j) & 1) ? '1' : '0';
- X if (i != size)
- X bitbuf[bp++] = ' ';
- X printed++;
- X }
- X bitbuf[bp++] = '\0';
- X return (bitbuf);
- X}
- X
- X/*
- X * Put a key in inverse video. This routine leaves the key in inverse video
- X * until the next key is pressed.
- X */
- Xstruct layout button[] = {
- X 'a', 6, 3, 'b', 6, 7, 'c', 6, 11, 'd', 6, 15, 'e', 6, 19,
- X 'f', 6, 23, '7', 6, 28, '8', 6, 32, '9', 6, 36, '/', 6, 40,
- X '?', 8, 3, 'F', 8, 7, 'h', 8, 11, 'H', 8, 11, 'D', 8, 15,
- X 'o', 8, 19, 'O', 8, 19, 'B', 8, 23, '4', 8, 28, '5', 8, 32,
- X '6', 8, 36, '*', 8, 40, '&', 10, 3, '|', 10, 7, 'l', 10, 11,
- X 'L', 10, 11, 'x', 10, 15, 'X', 10, 15, '\b', 10, 19, '\n', 10, 23,
- X '\r', 10, 23, '1', 10, 28, '2', 10, 32, '3', 10, 36, '-', 10, 40,
- X 'q', 12, 3, 'Q', 12, 3, '^', 12, 7, '~', 12, 11, 's', 12, 15,
- X 'S', 12, 15, 'r', 12, 19, 'R', 12, 19, '0', 12, 28, '.', 12, 32,
- X 'C', 12, 36, '+', 12, 40, '\0', 0, 0};
- X
- Xvoid
- Xflash_key(win, c)
- XWINDOW *win;
- Xchar c;
- X{
- X int i, n, temp_x, old_x, old_y;
- X static int last_y = 0, last_x = 0;
- X static char keybuf[3];
- X /* get x, y coordinates */
- X n = 0;
- X while (button[n].key != '\0') {
- X if (button[n].key == c)
- X break;
- X n++;
- X }
- X if (button[n].key == '\0')
- X return;
- X
- X getyx(win, old_y, old_x);
- X /* undo last button */
- X if (last_y) {
- X if (last_y == 10 && last_x == 23) {
- X for (i = 0; i < 3; i++) {
- X wmove(win, i + 10, 23);
- X wattrset(win, A_NORMAL);
- X waddstr(win, "<cr>");
- X }
- X }
- X else {
- X wmove(win, last_y, last_x);
- X wattrset(win, A_NORMAL);
- X waddstr(win, keybuf);
- X }
- X }
- X /* the enter key is 3x4 chars */
- X if (button[n].y == 10 && button[n].x == 23) {
- X for (i = 0; i < 3; i++) {
- X wmove(win, i + 10, 23);
- X wattron(win, A_REVERSE);
- X waddstr(win, "<cr>");
- X wattroff(win, A_REVERSE);
- X }
- X }
- X else { /* flash a button */
- X wmove(win, button[n].y, button[n].x);
- X wattron(win, A_REVERSE);
- X temp_x = button[n].x;
- X for (i = 0; i < 3; i++) {
- X keybuf[i] = what_is_at(win, button[n].y, temp_x++);
- X waddch(win, keybuf[i]);
- X }
- X wattroff(win, A_REVERSE);
- X }
- X wrefresh(win);
- X
- X wmove(win, old_y, old_x);
- X last_y = button[n].y;
- X last_x = button[n].x;
- X return;
- X}
- X
- X/*
- X * The image of the calculator.
- X */
- X
- Xvoid
- Xpaint_calc(win)
- XWINDOW *win;
- X{
- X void mybox();
- X int i;
- X
- X waddstr(win, " \n");
- X waddstr(win, " Reverse Polish Notation calculator v1.1 \n");
- X waddstr(win, " +---------------------------------------+ \n");
- X waddstr(win, " | | \n");
- X waddstr(win, " +---------------------------------------+ \n");
- X waddstr(win, " \n");
- X waddstr(win, " a b c d e f 7 8 9 / \n");
- X waddstr(win, " \n");
- X waddstr(win, " ? Flt Hex Dec Oct Bin 4 5 6 * \n");
- X waddstr(win, " \n");
- X waddstr(win, " & | roL Xy ^H <cr> 1 2 3 - \n");
- X waddstr(win, " <cr> \n");
- X waddstr(win, " Quit ^ ~ Sto Rcl <cr> 0 . Chs + \n");
- X waddstr(win, " \n");
- X
- X /*
- X * If you've got line drawing characters, build a box around the
- X * calculator display, replacing the crude one above.
- X */
- X#ifdef ACS_VLINE
- X for (i = 3; i < SCREEN_SIZE + 7; i++) {
- X mvwaddch(win, 2, i, ACS_HLINE);
- X mvwaddch(win, 4, i, ACS_HLINE);
- X }
- X mvwaddch(win, 3, 3, ACS_VLINE);
- X mvwaddch(win, 3, SCREEN_SIZE + 7, ACS_VLINE);
- X /* fix up corners */
- X mvwaddch(win, 2, 3, ACS_ULCORNER);
- X mvwaddch(win, 2, SCREEN_SIZE + 7, ACS_URCORNER);
- X mvwaddch(win, 4, 3, ACS_LLCORNER);
- X mvwaddch(win, 4, SCREEN_SIZE + 7, ACS_LRCORNER);
- X#endif /* ACS_VLINE */
- X
- X mybox(win);
- X wmove(win, 3, 5);
- X wrefresh(win);
- X return;
- X}
- X
- X/*
- X * A box() routine that will fix up the corners if your version of
- X * curses is too stupid to do that itself.
- X */
- X
- Xvoid
- Xmybox(win)
- XWINDOW *win;
- X{
- X#ifdef ACS_VLINE
- X box(win, 0, 0);
- X#else /* ACS_VLINE */
- X box(win, '|', '-');
- X mvwaddch(win, 0, 0, '+');
- X mvwaddch(win, 0, win->_maxx - 1, '+');
- X mvwaddch(win, win->_maxy - 1, 0, '+');
- X mvwaddch(win, win->_maxy - 1, win->_maxx - 1, '+');
- X#endif /* ACS_VLINE */
- X return;
- X}
- X
- X/*
- X * Clear the calculator "display" by writing blanks to it. Does not
- X * clear the hex/oct/dec/bin flag at the end.
- X */
- X
- Xvoid
- Xclear_display(win)
- XWINDOW *win;
- X{
- X mvwaddstr(win, 3, 5, blank);
- X wmove(win, 3, 5);
- X wrefresh(win);
- X return;
- X}
- X
- X/*
- X * The help screen... it really only gives a list of the abbreviations.
- X */
- X
- XWINDOW *
- Xhelp()
- X{
- X WINDOW *hwin, *newwin();
- X void mybox();
- X
- X hwin = newwin(14, 46, 2, 34);
- X waddstr(hwin, "\n RPN v1.1 - 18 Aug 89\n\n");
- X waddstr(hwin, " + add & logical and\n");
- X waddstr(hwin, " - subtract | logical or\n");
- X waddstr(hwin, " * multiply ^ exclusive or\n");
- X waddstr(hwin, " / divide ~ 1's complement\n");
- X waddstr(hwin, " <cr> enter key Chs change sign\n");
- X waddstr(hwin, " Flt float mode Sto store [0-9]\n");
- X waddstr(hwin, " Hex hex mode Rcl recall [0-9]\n");
- X waddstr(hwin, " Oct octal mode roL roll stack\n");
- X waddstr(hwin, " Bin binary mode Xy exchange x y\n");
- X mybox(hwin);
- X wrefresh(hwin);
- X return (hwin);
- X}
- X
- X#ifndef ANSI_C
- X#include <errno.h>
- X#include <ctype.h>
- Xextern int errno;
- X
- Xunsigned long
- Xstrtoul(buf, trailing, base)
- Xchar *buf;
- Xchar **trailing;
- Xint base;
- X{
- X int c;
- X unsigned long ans;
- X
- X ans = 0L;
- X
- X while (isspace(*buf))
- X buf++;
- X /* try to guess the base */
- X if (base == 0) {
- X if (*buf == '0') {
- X base = 8;
- X if (buf[1] == 'x' || buf[1] == 'X')
- X base = 16;
- X }
- X else
- X base = 10;
- X }
- X /* skip over '0x' and '0X' */
- X if (base == 16) {
- X if (*buf == '0' && (buf[1] == 'x' || buf[1] == 'X'))
- X buf += 2;
- X }
- X
- X while (1) {
- X c = *buf;
- X if (isdigit(c))
- X c -= '0';
- X else if (islower(c))
- X c -= 'a' - 10;
- X else if (isupper(c))
- X c -= 'A' - 10;
- X else /* unrecognized character, so stop */
- X break;
- X /* is this digit allowed? */
- X if (c >= base)
- X break;
- X
- X if ((ULONG_MAX - (unsigned int) c) / (unsigned int) base < ans) {
- X ans = ULONG_MAX;
- X errno = ERANGE;
- X break;
- X }
- X ans = ans * base + c;
- X buf++;
- X }
- X
- X if (trailing)
- X *trailing = buf;
- X
- X return (ans);
- X}
- X#endif /* ANSI_C */
- SHAR_EOF
- if test 19008 -ne "`wc -c < 'rpn.c'`"
- then
- echo shar: "error transmitting 'rpn.c'" '(should have been 19008 characters)'
- fi
- fi
- echo shar: "extracting 'rpn.1'" '(4028 characters)'
- if test -f 'rpn.1'
- then
- echo shar: "will not over-write existing file 'rpn.1'"
- else
- sed 's/^X//' << \SHAR_EOF > 'rpn.1'
- X.TH RPN 1 local
- X.SH NAME
- Xrpn \- an HP-16c reverse polish notation (rpn) calculator
- X.SH SYNOPSIS
- X.B rpn
- X[
- X.B \-d
- X]
- X.SH DESCRIPTION
- X.I Rpn
- Xis a ``pop up'' calculator for Unix and MSDOS that is designed to
- Xoperate similar to the Hewlett-Packard HP-16c (Computer Scientist)
- Xcalculator. It can operate in a floating point, hexidecimal, decimal,
- Xoctal, or binary mode.
- X.PP
- XThe
- X.I \-d
- Xoption is used to specify the number of decimal point precision that
- Xwill appear in the display. The internal precision of the calculator is
- Xnot affected.
- X.PP
- XThe calculator appears on the screen as:
- X.PP
- X.RS 5
- X.nf
- X+---------------------------------------------+
- X| Reverse Polish Notation calculator v1.1 |
- X| +---------------------------------------+ |
- X| | | |
- X| +---------------------------------------+ |
- X| |
- X| a b c d e f 7 8 9 / |
- X| |
- X| ? Flt Hex Dec Oct Bin 4 5 6 * |
- X| |
- X| & | roL Xy ^H <cr> 1 2 3 - |
- X| <cr> |
- X| Quit ^ ~ Sto Rcl <cr> 0 . Chs + |
- X| |
- X+---------------------------------------------+
- X.fi
- X.RE
- X.PP
- XThe ``buttons'' that appear on the screen turn to inverse video when the
- Xappropriate key on the keyboard is pressed.
- X.PP
- XReverse polish notation is an operating logic that envolves the use of
- Xthe ``enter'' key in lieu of an equal sign. To perform arithmetic,
- Xkey in the first number, press the ``enter'' key, key in the second
- Xnumber, and then press the operator. For example, to add 2 plus 3,
- Xyou type:
- X.PP
- X.RS 5
- X2 ``enter'' 3 +.
- X.RE
- X.PP
- XThe current mode of the calculator is displayed in the last
- Xposition on the ``screen'' as a blank, 'h', 'd', 'o', or 'b' for the
- Xfloating point, hexidecimal, decimal, octal, and binary modes
- Xrespectively.
- X.PP
- XThe use of the hex, decimal, octal, or binary modes implies that
- Xfractional parts of numbers are discarded and that negative numbers are
- Xdisplayed as a 2's complement.
- X.SH COMMANDS
- XThe
- X.I rpn
- Xprogram can perform the following mathematical and logical functions:
- X.PP
- X.RS 5
- X.nf
- X.if n .ta 2.5i
- X.if t .ta 2i
- X\fB+\fP addition \fB&\fP logical and
- X\fB-\fP subtraction \fB|\fP logical or
- X\fB*\fP multiplication \fB^\fP logical exculsive or
- X\fB/\fP division \fB~\fP 1's complement
- X.fi
- X.RE
- X.PP
- XThe following operators are also available:
- X.TP
- X.B ?
- XHelp screen. A pop-up help screen to explain the abreviations.
- X.TP
- X.B F
- XFloating point mode. Numbers with decimal points and/or exponents may
- Xbe used. Exponents are entered with the 'e' and may be followed by an
- Xoptional sign, as in 1.23e-12.
- X.TP
- X.B H
- XHexidecimal mode. Numbers use hexidecimal notation (digits in the range
- Xof 0-9 and a-f). The maximum hexidecimal number is 0xffffffff. To
- Xenter a hexidecimal digit in the range of a-f, you \fImust\fP use lower
- Xcase letters.
- X.TP
- X.B D
- XDecimal mode. Numbers use decimal notation (digits in the range of
- X0-9). The maximum decimal number is 4294967295.
- X.TP
- X.B O
- XOctal mode. Numbers use octal notation (digits in the range of 0-7).
- XThe maximum octal number is 0377777777777.
- X.TP
- X.B B
- Xbinary mode. Numbers use binary notation (the digits 0 and 1). The
- Xmaximum is 32 bits.
- X.TP
- X.B L
- XRoll the stack. The contents of the stack are ``rolled'' down by one
- Xposition.
- X.TP
- X.B X
- XExchange X and Y values. The last two values on the stack (X and Y)
- Xswap positions.
- X.TP
- X.B ^H
- XThe backspace key, to correct input.
- X.TP
- X.B ^M
- XThe ``enter'' key, shown as <cr> on the calculator.
- X.TP
- X.B Q
- XQuit. Exit the program.
- X.TP
- X.B S
- XStore a value in a register. Registers are numbered 0-9. To store a value
- Xin register 2, you enter S2.
- X.TP
- X.B R
- XRecall a value from a register. Registers are numbered 0-9.
- X.TP
- X.B C
- XChange sign. To enter a negative number, you first enter the number and
- Xthen change the sign.
- X.SH BUGS
- XMost operators are case sensitive.
- X.SH "SEE ALSO"
- Xdc(1), bc(1)
- SHAR_EOF
- if test 4028 -ne "`wc -c < 'rpn.1'`"
- then
- echo shar: "error transmitting 'rpn.1'" '(should have been 4028 characters)'
- fi
- fi
- echo shar: "extracting 'rpn.man'" '(5173 characters)'
- if test -f 'rpn.man'
- then
- echo shar: "will not over-write existing file 'rpn.man'"
- else
- sed 's/^X//' << \SHAR_EOF > 'rpn.man'
- X
- X
- X
- X RPN(1) (local) RPN(1)
- X
- X
- X
- X NAME
- X rpn - an HP-16c reverse polish notation (rpn) calculator
- X
- X SYNOPSIS
- X rpn [ -d ]
- X
- X DESCRIPTION
- X Rpn is a ``pop up'' calculator for Unix and MSDOS that is
- X designed to operate similar to the Hewlett-Packard HP-16c
- X (Computer Scientist) calculator. It can operate in a
- X floating point, hexidecimal, decimal, octal, or binary mode.
- X
- X The -d option is used to specify the number of decimal point
- X precision that will appear in the display. The internal
- X precision of the calculator is not affected.
- X
- X The calculator appears on the screen as:
- X
- X +---------------------------------------------+
- X | Reverse Polish Notation calculator v1.1 |
- X | +---------------------------------------+ |
- X | | | |
- X | +---------------------------------------+ |
- X | |
- X | a b c d e f 7 8 9 / |
- X | |
- X | ? Flt Hex Dec Oct Bin 4 5 6 * |
- X | |
- X | & | roL Xy ^H <cr> 1 2 3 - |
- X | <cr> |
- X | Quit ^ ~ Sto Rcl <cr> 0 . Chs + |
- X | |
- X +---------------------------------------------+
- X
- X The ``buttons'' that appear on the screen turn to inverse
- X video when the appropriate key on the keyboard is pressed.
- X
- X Reverse polish notation is an operating logic that envolves
- X the use of the ``enter'' key in lieu of an equal sign. To
- X perform arithmetic, key in the first number, press the
- X ``enter'' key, key in the second number, and then press the
- X operator. For example, to add 2 plus 3, you type:
- X
- X 2 ``enter'' 3 +.
- X
- X The current mode of the calculator is displayed in the last
- X position on the ``screen'' as a blank, 'h', 'd', 'o', or 'b'
- X for the floating point, hexidecimal, decimal, octal, and
- X binary modes respectively.
- X
- X The use of the hex, decimal, octal, or binary modes implies
- X that fractional parts of numbers are discarded and that
- X
- X
- X
- X Page 1
- X
- X
- X
- X
- X
- X
- X RPN(1) (local) RPN(1)
- X
- X
- X
- X negative numbers are displayed as a 2's complement.
- X
- X COMMANDS
- X The rpn program can perform the following mathematical and
- X logical functions:
- X
- X + addition & logical and
- X - subtraction | logical or
- X * multiplication ^ logical exculsive or
- X / division ~ 1's complement
- X
- X The following operators are also available:
- X
- X ? Help screen. A pop-up help screen to explain the
- X abreviations.
- X
- X F Floating point mode. Numbers with decimal points
- X and/or exponents may be used. Exponents are entered
- X with the 'e' and may be followed by an optional sign,
- X as in 1.23e-12.
- X
- X H Hexidecimal mode. Numbers use hexidecimal notation
- X (digits in the range of 0-9 and a-f). The maximum
- X hexidecimal number is 0xffffffff. To enter a
- X hexidecimal digit in the range of a-f, you must use
- X lower case letters.
- X
- X D Decimal mode. Numbers use decimal notation (digits in
- X the range of 0-9). The maximum decimal number is
- X 4294967295.
- X
- X O Octal mode. Numbers use octal notation (digits in the
- X range of 0-7). The maximum octal number is
- X 0377777777777.
- X
- X B binary mode. Numbers use binary notation (the digits 0
- X and 1). The maximum is 32 bits.
- X
- X L Roll the stack. The contents of the stack are
- X ``rolled'' down by one position.
- X
- X X Exchange X and Y values. The last two values on the
- X stack (X and Y) swap positions.
- X
- X ^H The backspace key, to correct input.
- X
- X ^M The ``enter'' key, shown as <cr> on the calculator.
- X
- X Q Quit. Exit the program.
- X
- X S Store a value in a register. Registers are numbered
- X 0-9. To store a value in register 2, you enter S2.
- X
- X
- X
- X Page 2
- X
- X
- X
- X
- X
- X
- X RPN(1) (local) RPN(1)
- X
- X
- X
- X R Recall a value from a register. Registers are numbered
- X 0-9.
- X
- X C Change sign. To enter a negative number, you first
- X enter the number and then change the sign.
- X
- X BUGS
- X Most operators are case sensitive.
- X
- X SEE ALSO
- X dc(1), bc(1)
- X
- X
- X
- X
- X
- X
- X
- X
- X
- X
- X
- X
- X
- X
- X
- X
- X
- X
- X
- X
- X
- X
- X
- X
- X
- X
- X
- X
- X
- X
- X
- X
- X
- X
- X
- X
- X
- X
- X
- X
- X
- X
- X
- X
- X Page 3
- X
- X
- X
- SHAR_EOF
- if test 5173 -ne "`wc -c < 'rpn.man'`"
- then
- echo shar: "error transmitting 'rpn.man'" '(should have been 5173 characters)'
- fi
- fi
- exit 0
- # End of shell archive
-
-
-